package sklad;

import data.ExtramobiExcel;
import data.ItemData;
import jxl.Workbook;
import jxl.WorkbookSettings;
import jxl.format.*;
import jxl.format.Colour;
import jxl.read.biff.BiffException;
import jxl.write.*;
import jxl.write.Number;
import org.apache.poi.hslf.model.Comment;
import org.apache.poi.hssf.usermodel.*;
import org.apache.poi.hssf.util.HSSFColor;
import org.apache.poi.ss.usermodel.*;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.*;

/**
 * User: Vladimir
 * Date: 23.09.12 Time: 18:57
 */
public class StoreManager {
    public Map<StoreEnum, List<GoodItem>> storages = new HashMap<StoreEnum, List<GoodItem>>();
    //    public Map<StoreEnum, List<GoodItem>> sold = new HashMap<StoreEnum, List<GoodItem>>();
//    public List<GoodItem> allItems = new ArrayList<GoodItem>();
    public Map<Short, HSSFCellStyle> styles = new HashMap<Short, HSSFCellStyle>();

    public static void main(String[] args) throws BiffException, IOException, WriteException, CloneNotSupportedException, IllegalAccessException {
//        Map<String, List<ItemData>> allGoods = AllGoodsManager.getAllItemData();
        List<String> exceptionList = new ArrayList<String>();
        exceptionList.add("phone.xls");
        exceptionList.add("remont.xls");

        Map<String, List<ItemData>> allGoods = ExtramobiExcel.parseItemData("data/test3", exceptionList, false);
        StoreManager manager = new StoreManager();
        manager.init(allGoods);
        String path = "sklad2/income";
        File incomeFolder = new File(path);
        for (File incomeFile : incomeFolder.listFiles()) {
            if (incomeFile.getName().contains("svn")) {
                continue;
            }
            StoreEnum store = Parser.parseStore(incomeFile);
            List<GoodItem> items = Parser.parseXlsPOI(incomeFile.getPath());
            manager.incomeGoods(store, items);
        }
        List<GoodItem> items = RemainsGrabber.grabGlavpunkt();
        manager.incomeGoods(StoreEnum.ALTAYSKAYA, items);
        items = RemainsGrabber.grabZaberiTovar();
        manager.incomeGoods(StoreEnum.ENGELSA, items);
        path = "sklad2/remains";
        File remainsFolder = new File(path);
        for (File remainsFile : remainsFolder.listFiles()) {
            if (remainsFile.getName().contains("svn")) {
                continue;
            }
            StoreEnum store = Parser.parseStore(remainsFile);
            if (store.equals(StoreEnum.GOROHOVAYA)) {
                items = Parser.parseRemainsGorohovayaPOI(remainsFile.getPath());
            } else {
                throw new IllegalStateException("Unknown remains store type: " + store);
            }
            manager.incomeGoods(store, items);
        }
        manager.saveToXlsPOI("sklad2/остатки.xls");
//        List<GoodItem> inItems = Parser.parseXls("G:\\projects\\my-im-tools\\sklad\\in-bills\\ISA 19.09.12.xls");
//        StoreManager manager = new StoreManager();
//        manager.incomeGoods(StoreEnum.SEDOVA, inItems);
//        manager.moveItems(StoreEnum.SEDOVA, StoreEnum.ALTAYSKAYA, inItems);
//        inItems = Parser.parseXls("G:\\projects\\my-im-tools\\sklad\\in-bills\\ISA 27.09.12.xls");
//        manager.incomeGoods(StoreEnum.SEDOVA, inItems);
//        manager.moveItems(StoreEnum.SEDOVA, StoreEnum.GOROHOVAYA, inItems);
//        inItems = Parser.parseXls("G:\\projects\\my-im-tools\\sklad\\in-bills\\ISA 27.09.12.xls");
//        manager.sellItems(StoreEnum.GOROHOVAYA, inItems);
//        for (StoreEnum store : manager.storages.keySet()) {
//            List<GoodItem> items = manager.storages.get(store);
//            System.out.println(store.name + " : ");
//            for (GoodItem item : items) {
//                System.out.println(item);
//            }
//        }
//        for (StoreEnum store : manager.sold.keySet()) {
//            List<GoodItem> items = manager.sold.get(store);
//            System.out.println(store.name + " : ");
//            for (GoodItem item : items) {
//                System.out.println(item);
//            }
//        }
    }

    private void init(Map<String, List<ItemData>> allGoods) throws CloneNotSupportedException {
        List<GoodItem> items = new ArrayList<GoodItem>();
        for (String category : allGoods.keySet()) {
            for (ItemData data : allGoods.get(category)) {
                GoodItem item = new GoodItem();
                item.article = data.article;
                item.name = data.name;
                item.count = 0;
                item.category = category;
                item.sellPrice = data.price;
                items.add(item);
            }
        }
        for (StoreEnum store : StoreEnum.values()) {
            List<GoodItem> copyItems = new ArrayList<GoodItem>();
            incomeGoods(store, copyItems);
            for (GoodItem item : items) {
                GoodItem cloneItem = (GoodItem) item.clone();
                copyItems.add(cloneItem);
            }
        }
    }


    public void incomeGoods(StoreEnum store, List<GoodItem> items) {
        if (!storages.containsKey(store)) {
            storages.put(store, items);
//            for (GoodItem currItem : items) {
//                if (!allItems.contains(currItem)) {
//                    allItems.add(currItem);
//                }
//                if (isCheck(currItem)) {
//                    System.out.println("Income: " + currItem);
//                }
//            }
        } else {
            List<GoodItem> currentItems = storages.get(store);
            for (GoodItem item : items) {
                if (currentItems.contains(item)) {
                    GoodItem currItem = currentItems.get(currentItems.indexOf(item));
                    currItem.buyPrice = item.buyPrice;
//                    currItem.sellPrice = item.sellPrice;
                    currItem.count += item.count;
                    currItem.supplier = item.supplier;
//                    currItem.name = item.name;
                } else {
                    currentItems.add(item);
                }
//                if (!allItems.contains(item)) {
//                    allItems.add(item);
//                }
                if (isCheck(item)) {
                    System.out.println("Income: " + item);
                }
            }
        }
    }

    private boolean isCheck(GoodItem item) {
//        return item.article.equals("1001010");
//        return item.name.contains("-4L");
        return false;
    }

    public void resumeRemains(Map<StoreEnum, List<GoodItem>> remainsByStore) {
        for (StoreEnum store : remainsByStore.keySet()) {
            resumeRemains(store, remainsByStore.get(store));
        }
    }

    private void resumeRemains(StoreEnum store, List<GoodItem> remains) {
        if (!storages.containsKey(store)) {
            throw new IllegalArgumentException("Unknown store store: " + store);
        }
        List<GoodItem> currentItems = storages.get(store);
        List<GoodItem> soldItems = new ArrayList<GoodItem>();
        for (GoodItem currItem : currentItems) {
            if (remains.contains(currItem)) {
                int restCount = remains.get(remains.indexOf(currItem)).count;
                if (restCount != currItem.count) {
                    GoodItem soldItem = GoodItem.copyItem(currItem);
                    soldItem.count = currItem.count - restCount;
                    soldItems.add(soldItem);
                }
            }
        }
        sellItems(store, soldItems);
    }

    public void sellItems(StoreEnum store, List<GoodItem> items) {
        if (!storages.containsKey(store)) {
            throw new IllegalArgumentException("Unknown store store: " + store);
        }
        List<GoodItem> currentItems = storages.get(store);
        for (GoodItem item : items) {
            if (currentItems.contains(item)) {
                GoodItem currItem = currentItems.get(currentItems.indexOf(item));
//                currItem.buyPrice = item.buyPrice;
//                currItem.sellPrice = item.sellPrice;
//                putInsold(store, item);
                currItem.count -= item.count;
                currItem.sellCount += item.count;
//                currItem.supplier = item.supplier;
//                currItem.name = item.name;
            } else {
                throw new IllegalArgumentException(store.name + " does not contain an item " + item);
            }
            if (isCheck(item)) {
                System.out.println("Sold: " + item.count + " from " + store.name);
            }
        }
//        for (GoodItem currItem : currentItems) {
//            if (items.contains(currItem)) {
//                GoodItem item = items.get(items.indexOf(currItem));
//                currItem.buyPrice = item.buyPrice;
//                currItem.sellPrice = item.sellPrice;
//                currItem.count -= item.count;
//                currItem.supplier = item.supplier;
//                currItem.name = item.name;
//            }
//        }
    }

    /* private void putInsold(StoreEnum store, GoodItem item) {
        List<GoodItem> items;
        if (sold.containsKey(store)) {
            items = sold.get(store);
        } else {
            items = new ArrayList<GoodItem>();
            sold.put(store, items);
        }
        if (items.contains(item)) {
            GoodItem currItem = items.get(items.indexOf(item));
            currItem.sellCount += item.count;
        } else {
            GoodItem currItem = GoodItem.copyItem(item);
            currItem.sellCount = item.count;
            items.add(currItem);
        }
    }*/

    public void moveItems(StoreEnum fromStore, Map<StoreEnum, List<GoodItem>> itemsByStore) {
        for (StoreEnum toStore : itemsByStore.keySet()) {
            moveItems(fromStore, toStore, itemsByStore.get(toStore));
        }
    }

//    public void moveItems(StoreEnum fromStore, StoreEnum toStore, List<GoodItem> itemsToMove) {
//        if (!storages.containsKey(fromSource)) {
//            throw new IllegalArgumentException("Unknown store house: " + fromSource);
//        }
//        if (!storages.containsKey(toSource)) {
//            throw new IllegalArgumentException("Unknown store house: " + toSource);
//        }
//        moveItems(fromStore, toStore, itemsToMove);
//        incomeGoods(toStore, itemsToMove);
//    }


    public void moveItems(StoreEnum fromStore, StoreEnum toStore, List<GoodItem> itemsToMove) {
        List<GoodItem> fromItems = storages.get(fromStore);
        List<GoodItem> toItems;
        if (!storages.containsKey(toStore)) {
            toItems = new ArrayList<GoodItem>();
            storages.put(toStore, toItems);
        } else {
            toItems = storages.get(toStore);
        }
//        moveItems();
        for (GoodItem itemToMove : itemsToMove) {
            if (!fromItems.contains(itemToMove)) {
                throw new IllegalArgumentException("SourceEnum " + fromStore + " does not contain item: " + itemToMove);
            }
            GoodItem fromItem = fromItems.get(fromItems.indexOf(itemToMove));
            GoodItem toItem;
            if (toItems.contains(itemToMove)) {
                toItem = toItems.get(toItems.indexOf(itemsToMove));
            } else {
                toItem = GoodItem.copyItem(itemToMove);
                toItem.count = 0;
            }
            toItem.buyPrice = itemToMove.buyPrice;
//            GoodItem toItem = itemsToMove.get(itemsToMove.indexOf(fromItem));
            toItem.count += itemToMove.count;
            fromItem.count -= itemToMove.count;
            if (!toItems.contains(itemToMove)) {
                toItems.add(toItem);
            }
            if (fromItem.count < 0) {
                throw new IllegalStateException("Move count exceeded storage: " + itemToMove);
            }
            if (isCheck(itemToMove)) {
                System.out.println("Moved from " + fromStore.name + " to" + toStore.name + ": " + itemToMove.count);
            }

        }
    }

    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();
        for (StoreEnum store : storages.keySet()) {
            List<GoodItem> items = storages.get(store);
            sb.append(store.name).append(": \n");
            for (GoodItem item : items) {
                sb.append(item).append("\n");
            }
        }
        return sb.toString();
    }

    public void saveToXlsPOI(String xlsFile) throws IOException, WriteException {
        HSSFWorkbook wb = new HSSFWorkbook();
        FileOutputStream fileOut = new FileOutputStream(xlsFile);
        HSSFSheet sheet = wb.createSheet("Остатки");
        int column = 0;
        HSSFRow headerRow = sheet.createRow(0);
        headerRow.createCell(column++).setCellValue("№");
        headerRow.createCell(column++).setCellValue("Артикул");
        headerRow.createCell(column++).setCellValue("Наименование");
        List<StoreEnum> values = Arrays.asList(StoreEnum.values());
        Collections.sort(values, new Comparator<StoreEnum>() {
            @Override
            public int compare(StoreEnum o1, StoreEnum o2) {
                return o1.name.compareTo(o2.name);
            }
        });
        for (StoreEnum store : values) {
            HSSFCell cell = headerRow.createCell(column++);
            cell.setCellValue(store.name);
            sheet.autoSizeColumn(cell.getColumnIndex());
        }
        headerRow.createCell(column++).setCellValue("Всего");
        headerRow.createCell(column++).setCellValue("Цена");
        int rowNum = 1;
        List<GoodItem> allItems = storages.get(StoreEnum.GOROHOVAYA);
        Collections.sort(allItems, new Comparator<GoodItem>() {
            @Override
            public int compare(GoodItem o1, GoodItem o2) {
                return o1.article.compareTo(o2.article);
            }
        });
        for (GoodItem item : allItems) {
            column = 0;
            HSSFRow row = sheet.createRow(rowNum);
            row.createCell(column++).setCellValue(rowNum);
            row.createCell(column++).setCellValue(item.article);
            HSSFCell cell = row.createCell(column++);
            cell.setCellValue(item.name);
//            sheet.autoSizeColumn(cell.getColumnIndex());
            int summCount = 0;

            for (StoreEnum store : values) {
                List<GoodItem> storeItems = storages.get(store);
                int itemsCount = 0;
                if (storeItems == null) {
                    column++;
                    continue;
                }
                if (storeItems.contains(item)) {
                    item = storeItems.get(storeItems.indexOf(item));
                    itemsCount = item.count;
                    summCount += itemsCount;
                }
                cell = row.createCell(column++);
                cell.setCellValue(itemsCount);
                colorCell(wb, cell, itemsCount);
                setCellTooltip(cell, store.name);
            }
            cell = row.createCell(column++);
            cell.setCellValue(summCount);
            colorCell(wb, cell, summCount);
            cell = row.createCell(column++);
            cell.setCellValue(item.sellPrice);
            rowNum++;
        }
        sheet.autoSizeColumn(2);
//        headerRow.createCell(3).setCellValue("Наименование");
        wb.write(fileOut);
        fileOut.close();
    }

    private void setCellTooltip(HSSFCell cell, String tooltip) {
        Drawing drawing = cell.getSheet().createDrawingPatriarch();
        CreationHelper factory = cell.getSheet().getWorkbook()
                .getCreationHelper();
        // When the comment box is visible, have it show in a 1x3 space
        ClientAnchor anchor = factory.createClientAnchor();
        anchor.setCol1(cell.getColumnIndex());
        anchor.setCol2(cell.getColumnIndex() + 2);
        anchor.setRow1(cell.getRowIndex());
        anchor.setRow2(cell.getRowIndex() + 2);
//        anchor.setDx1(100);
//        anchor.setDx2(100);
//        anchor.setDy1(100);
//        anchor.setDy2(100);

        // Create the comment and set the text+author
        org.apache.poi.ss.usermodel.Comment comment = drawing.createCellComment(anchor);
        RichTextString str = factory.createRichTextString(tooltip);
        comment.setString(str);
//        comment.setAuthor("Apache POI");
        // Assign the comment to the cell
        cell.setCellComment(comment);
    }

    public void saveToXls(String xlsFile) throws IOException, WriteException {
        WorkbookSettings s = new WorkbookSettings();
        s.setLocale(new Locale("ru", "RU"));
        s.setEncoding("KOI8-R");
        WritableWorkbook workbook = Workbook.createWorkbook(new File(xlsFile), s);
        workbook.createSheet("Остатки", 0);
        WritableSheet sheet = workbook.getSheet(0);

        // header
        int count = 0;
        WritableCell cell = new Label(count++, 0, "Номер");
        Parser.autoFitWidth(sheet, count);
        sheet.addCell(cell);
        cell = new Label(count++, 0, "Артикул");
        Parser.autoFitWidth(sheet, count);
        sheet.addCell(cell);
        cell = new Label(count++, 0, "Название");
        Parser.autoFitWidth(sheet, count);
        sheet.addCell(cell);
        for (StoreEnum store : StoreEnum.values()) {
            cell = new Label(count++, 0, store.name);
            Parser.autoFitWidth(sheet, count);
            sheet.addCell(cell);
            cell = new Label(count++, 0, "продано");
            Parser.autoFitWidth(sheet, count);
            sheet.addCell(cell);
        }
        cell = new Label(count++, 0, "Итого");
        Parser.autoFitWidth(sheet, count);
        sheet.addCell(cell);
        Parser.autoFitWidth(sheet, count);
        cell = new Label(count++, 0, "Продано");
        sheet.addCell(cell);

        //items
        List<GoodItem> allItems = storages.get(StoreEnum.GOROHOVAYA);
        Collections.sort(allItems, new Comparator<GoodItem>() {
            @Override
            public int compare(GoodItem o1, GoodItem o2) {
                return o1.article.compareTo(o2.article);
            }
        });
        int row = 1;
        for (GoodItem item : allItems) {
            count = 0;
            cell = new Number(count++, row, row);
            Parser.autoFitWidth(sheet, count);
            sheet.addCell(cell);
            cell = new Label(count++, row, item.article);
            Parser.autoFitWidth(sheet, count);
            sheet.addCell(cell);
            cell = new Label(count++, row, item.name);
            Parser.autoFitWidth(sheet, count);
            sheet.addCell(cell);
            int summCount = 0;
            int summSellCount = 0;
            for (StoreEnum store : StoreEnum.values()) {
                List<GoodItem> storeItems = storages.get(store);
                int itemsCount = 0;
                int sellCount = 0;
                if (storeItems == null) {
                    count++;
                    continue;
                }
                if (storeItems.contains(item)) {
                    item = storeItems.get(storeItems.indexOf(item));
                    itemsCount = item.count;
                    sellCount = item.sellCount;
                    summCount += itemsCount;
                }
                cell = new Number(count++, row, itemsCount);
                Parser.autoFitWidth(sheet, count);
                sheet.addCell(cell);
                colorCell(cell, itemsCount);
                cell = new Number(count++, row, sellCount);
                Parser.autoFitWidth(sheet, count);
                sheet.addCell(cell);
                summSellCount += sellCount;
            }
            cell = new Number(count++, row, summCount);
            colorCell(cell, summCount);
            Parser.autoFitWidth(sheet, count);
            sheet.addCell(cell);
            cell = new Number(count++, row, summSellCount);
            Parser.autoFitWidth(sheet, count);
            sheet.addCell(cell);
            row++;
        }
        workbook.write();
        workbook.close();
    }

    private void colorCell(HSSFWorkbook wb, HSSFCell cell, int count) throws WriteException {
        HSSFCellStyle style;
        if (count > 20) {
            if (styles.containsKey(HSSFColor.GREEN.index)) {
                style = styles.get(HSSFColor.GREEN.index);
            } else {
                style = wb.createCellStyle();
                style.setFillForegroundColor(HSSFColor.GREEN.index);
                style.setFillPattern(CellStyle.SOLID_FOREGROUND);
                styles.put(HSSFColor.GREEN.index, style);
            }
        } else if (count == 0) {
            if (styles.containsKey(HSSFColor.RED.index)) {
                style = styles.get(HSSFColor.RED.index);
            } else {
                style = wb.createCellStyle();
                style.setFillForegroundColor(HSSFColor.RED.index);
                style.setFillPattern(CellStyle.SOLID_FOREGROUND);
                styles.put(HSSFColor.RED.index, style);
            }
        } else if (count == 1) {
            if (styles.containsKey(HSSFColor.ORANGE.index)) {
                style = styles.get(HSSFColor.ORANGE.index);
            } else {
                style = wb.createCellStyle();
                style.setFillForegroundColor(HSSFColor.ORANGE.index);
                style.setFillPattern(CellStyle.SOLID_FOREGROUND);
                styles.put(HSSFColor.ORANGE.index, style);
            }
        } else if (count < 5) {
            if (styles.containsKey(HSSFColor.YELLOW.index)) {
                style = styles.get(HSSFColor.YELLOW.index);
            } else {
                style = wb.createCellStyle();
                style.setFillForegroundColor(HSSFColor.YELLOW.index);
                style.setFillPattern(CellStyle.SOLID_FOREGROUND);
                styles.put(HSSFColor.YELLOW.index, style);
            }
        } else {
            if (styles.containsKey(HSSFColor.WHITE.index)) {
                style = styles.get(HSSFColor.WHITE.index);
            } else {
                style = wb.createCellStyle();
                style.setFillForegroundColor(HSSFColor.WHITE.index);
                style.setFillPattern(CellStyle.SOLID_FOREGROUND);
                styles.put(HSSFColor.WHITE.index, style);
            }
        }
        cell.setCellStyle(style);
    }

    private void colorCell(WritableCell cell, int count) throws WriteException {
        if (count > 20) {
            cell.setCellFormat(getGreen());
        } else if (count == 0) {
            cell.setCellFormat(getRed());
        } else if (count == 1) {
            cell.setCellFormat(getOrange());
        } else if (count < 5) {
            cell.setCellFormat(getYellow());
        }
    }

    private WritableCellFormat getYellow() throws WriteException {
        WritableCellFormat format = new WritableCellFormat();
        format.setBackground(Colour.YELLOW);
        return format;
    }

    private WritableCellFormat getRed() throws WriteException {
        WritableCellFormat format = new WritableCellFormat();
        format.setBackground(Colour.RED);
        return format;
    }

    public CellFormat getGreen() throws WriteException {
        WritableCellFormat format = new WritableCellFormat();
        format.setBackground(Colour.GREEN);
        return format;

    }

    public CellFormat getOrange() throws WriteException {
        WritableCellFormat format = new WritableCellFormat();
        format.setBackground(Colour.ORANGE);
        return format;

    }
}
